/**
 * 主题处理
 * v5.1.0新增
 */
import { fetchValueByCode } from '@/api/system/settings'

class Theme {
  // 系统主题设置（通过系统设置/主题设置进行修改）
  #themeSettings = null
  // 默认主题设置
  #defaultSettings = {
    // 主色调
    primaryColor: '#2d8cf0',
    // 头部设置
    headerHeight: 60,
    // 菜单设置
    menuBackgroundColor: '#2f3044',
    menuHoverBackgroundColor: '#36374f',
    submenuBackgroundColor: '#292a3d',
    menuTextColor: '#9f9f9f',
    menuTextHoverColor: '#f7f7f7',
    menuActiveRadio: 10,
    menuWidth: 218,
  }
  // 明亮模式默认值
  light = {
    mode: 'light',
    // 基础
    lightColor: '#ffffff',
    darkColor: '#000000',
    grayColor: '#999999',
    deepGrayColor: '#555555',
    fontColor: '#333333',
    borderColor: '#eeeeee',
    backgroundColor: '#f7f7f7',
    // 头部
    headerBackgroundColor: '#fff',
    headerTextColor: '#333',
    // 表格
    tableHeaderFontColor: '#666',
    tableHeaderBackgroundColor: '#f8f8f9',
    // 菜单
    menuActiveTextColor: '#333',
    menuActiveTextHoverColor: '#333',
  }
  // 暗黑模式默认值
  dark = {
    mode: 'dark',
    // 基础
    lightColor: '#2f3044',
    darkColor: '#ffffff',
    grayColor: '#d3d3d3',
    deepGrayColor: '#e7e7e7',
    fontColor: '#f0f0f0',
    borderColor: '#555',
    backgroundColor: '#171A33',
    // 头部
    headerBackgroundColor: '#2f3044',
    headerTextColor: '#fff',
    // 表格
    tableHeaderFontColor: '#f0f0f0',
    tableHeaderBackgroundColor: '#171A33',
    // 菜单
    menuActiveTextColor: '#d3d3d3',
    menuActiveTextHoverColor: '#d3d3d3',
  }
  constructor () {
    // 构建默认主题为明亮模式
    Object.assign(this.#defaultSettings, this.light)
  }
  // 初始化主题
  async init () {
    try {
      const data = await fetchValueByCode('theme-settings')
      if (data == null) {
        return
      }
      this.#themeSettings = JSON.parse(data)
      this.setTheme(this.#themeSettings)
    } catch (e) {
      console.error('主题初始化失败', e)
    }
  }

  /**
   * 设置主题
   *
   * @param themeSetting 主题设置对象
   */
  setTheme (themeSetting) {
    if (this.#themeSettings == null) {
      this.#themeSettings = {}
    }
    Object.assign(this.#themeSettings, themeSetting)
    // 为html添加风格class
    document.documentElement.classList.remove('dark')
    document.documentElement.classList.remove('light')
    if (this.isDarkMode()) {
      document.documentElement.classList.add('dark')
    } else {
      document.documentElement.classList.add('light')
    }
    // 将配置项补充到根对象中
    for (const key in this.#themeSettings) {
      this[key] = this.#themeSettings[key]
    }
    // 基础设置
    this.setCssVariable('--color-primary', themeSetting.primaryColor)
    this.setCssVariable('--color-primary-dark', this.offsetColor(themeSetting.primaryColor, -50))
    this.setCssVariable('--color-primary-light', this.offsetColor(themeSetting.primaryColor, 50))
    this.setCssVariable('--background-color', themeSetting.backgroundColor)
    this.setCssVariable('--font-color', themeSetting.fontColor)
    this.setCssVariable('--color-gray-deep', themeSetting.deepGrayColor)
    this.setCssVariable('--color-gray', themeSetting.grayColor)
    this.setCssVariable('--border-color', themeSetting.borderColor)
    this.setCssVariable('--color-light', themeSetting.lightColor)
    // 头部设置
    this.setCssVariable('--header-height', `${themeSetting.headerHeight}px`)
    this.setCssVariable('--header-background-color', themeSetting.headerBackgroundColor)
    this.setCssVariable('--header-text-color', themeSetting.headerTextColor)
    // 表格设置
    this.setCssVariable('--table-header-background-color', themeSetting.tableHeaderBackgroundColor)
    this.setCssVariable('--table-header-font-color', themeSetting.tableHeaderFontColor)
    // 菜单设置
    this.setCssVariable('--menu-background-color', themeSetting.menuBackgroundColor)
    this.setCssVariable('--menu-hover-background-color', themeSetting.menuHoverBackgroundColor)
    this.setCssVariable('--submenu-background-color', themeSetting.submenuBackgroundColor)
    this.setCssVariable('--menu-text-color', themeSetting.menuTextColor)
    this.setCssVariable('--menu-text-hover-color', themeSetting.menuTextHoverColor)
    this.setCssVariable('--menu-active-background-color', themeSetting.backgroundColor)
    this.setCssVariable('--menu-active-text-color', themeSetting.menuActiveTextColor)
    this.setCssVariable('--menu-active-text-hover-color', themeSetting.menuActiveTextHoverColor)
    this.setCssVariable('--menu-active-radius-size', `${themeSetting.menuActiveRadio}px`)
    this.setCssVariable('--menu-width', `${themeSetting.menuWidth}px`)
    // element plus主题设置
    // - 主题色调整
    this.setCssVariable('--el-color-primary', themeSetting.primaryColor)
    // - 主题色提亮，9个度
    for (let i = 1; i <= 9; i++) {
      this.setCssVariable(`--el-color-primary-light-${i}`, this.offsetColor(themeSetting.primaryColor, i * 10))
    }
    // - 主题色暗化，2个度
    this.setCssVariable('--el-color-primary-dark-2', this.offsetColor(themeSetting.primaryColor, -20))
    // - 组件的通用背景色，如表格行的背景色
    this.setCssVariable('--el-bg-color', themeSetting.lightColor)
  }
  // 判断是否为暗黑模式
  isDarkMode () {
    return this.#themeSettings.mode === 'dark'
  }
  // 获取设置
  getSettings () {
    if (this.#themeSettings == null) {
      return this.#defaultSettings
    }
    return this.#themeSettings
  }
  // 获取默认设置
  getDefaultSettings () {
    return this.#defaultSettings
  }

  /**
   * 16进制颜色转rgba
   *
   * @param hexColor 16进制色值
   * @param opacity 透明度
   * @returns {string}
   */
  rgba (hexColor, opacity) {
    const r = parseInt('0x' + hexColor.slice(1, 3))
    const g = parseInt('0x' + hexColor.slice(3, 5))
    const b = parseInt('0x' + hexColor.slice(5, 7))
    return `rgba(${r},${g},${b},${opacity})`
  }

  /**
   * 变更颜色
   *
   * @param color 颜色值，支持16进制颜色值、rgb和rgba
   * @param percent 百分比
   * @returns {string}
   */
  offsetColor (color, percent) {
    let r, g, b, opacity = 1
    // 16进制色值
    if (color.startsWith('#')) {
      r = parseInt('0x' + color.slice(1, 3))
      g = parseInt('0x' + color.slice(3, 5))
      b = parseInt('0x' + color.slice(5, 7))
    }
    // rgb或rgba色值
    else if (color.startsWith('rgb')) {
      const rgb = color
        .slice(color.indexOf('(') + 1, color.indexOf(')'))
        .split(',')
        .map(v => parseInt(v.trim()))
      r = rgb[0]
      g = rgb[1]
      b = rgb[2]
      // 根据同明度计算色值
      opacity = rgb[3] === undefined ? 1 : rgb[3]
      r *= opacity
      g *= opacity
      b *= opacity
    }
    // 计算新色值
    r = Math.round(r + (255 - r) * (percent / 100))
    g = Math.round(g + (255 - g) * (percent / 100))
    b = Math.round(b + (255 - b) * (percent / 100))
    r = r < 0 ? 0 : r > 255 ? 255 : r
    g = g < 0 ? 0 : g > 255 ? 255 : g
    b = b < 0 ? 0 : b > 255 ? 255 : b
    return `rgba(${r},${g},${b},${opacity})`
  }

  /**
   * 设置CSS变量
   *
   * @param variable 变量名
   * @param value 值
   */
  setCssVariable (variable, value) {
    if (value == null || value === '' || value === 'nullpx') {
      return
    }
    document.documentElement.style.setProperty(variable, value)
  }
}
export default new Theme()
